<script lang="ts" setup>
import { useClipboard } from '@vueuse/core'
import { ElMessage } from 'element-plus'
import { computed, ref, watch } from 'vue'

// 支持的进制类型
const baseTypes = [
  { value: 2, label: '二进制 (Base 2)' },
  { value: 8, label: '八进制 (Base 8)' },
  { value: 10, label: '十进制 (Base 10)' },
  { value: 16, label: '十六进制 (Base 16)' },
  { value: 32, label: '三十二进制 (Base 32)' },
  { value: 36, label: '三十六进制 (Base 36)' },
]

// 输入值和选择的进制
const inputValue = ref('')
const selectedBase = ref(10)

// 转换结果
const conversionResults = ref<{ base: number, value: string }[]>([])

// 错误信息
const errorMessage = ref('')

// 复制功能
const { copy } = useClipboard()

// 监听输入值和选择的进制变化
watch([inputValue, selectedBase], () => {
  convertBase()
})

// 进制转换函数
function convertBase() {
  // 清除之前的错误
  errorMessage.value = ''

  // 如果输入为空，清空结果
  if (!inputValue.value.trim()) {
    conversionResults.value = []
    return
  }

  try {
    // 将输入值从选定的进制转换为十进制
    const decimalValue = Number.parseInt(inputValue.value, selectedBase.value)

    // 检查是否为有效数字
    if (Number.isNaN(decimalValue)) {
      throw new TypeError(`无效的${getBaseName(selectedBase.value)}数字`)
    }

    // 转换为所有支持的进制
    conversionResults.value = baseTypes.map((baseType) => {
      return {
        base: baseType.value,
        value: decimalValue.toString(baseType.value).toUpperCase(),
      }
    })
  }
  catch (error) {
    errorMessage.value = (error as Error).message
    conversionResults.value = []
  }
}

// 获取进制名称
function getBaseName(base: number): string {
  const baseType = baseTypes.find(type => type.value === base)
  return baseType ? baseType.label : `Base ${base}`
}

// 复制结果
function copyResult(value: string) {
  copy(value)
  ElMessage.success('已复制到剪贴板')
}

// 清空输入
function clearInput() {
  inputValue.value = ''
  conversionResults.value = []
  errorMessage.value = ''
}

// 设置输入值为指定进制的结果
function setAsInput(base: number, value: string) {
  inputValue.value = value
  selectedBase.value = base
}

// 格式化显示的进制值
function formatBaseValue(base: number, value: string): string {
  if (base === 2) {
    return `0b${value}`
  }
  if (base === 8) {
    return `0${value}`
  }
  if (base === 16) {
    return `0x${value}`
  }
  return value
}

// 计算输入是否有效
const isValidInput = computed(() => {
  if (!inputValue.value.trim()) {
    return true
  }

  // 根据选定的进制检查输入是否有效
  const regex = {
    2: /^[01]+$/,
    8: /^[0-7]+$/,
    10: /^\d+$/,
    16: /^[0-9A-F]+$/i,
    32: /^[0-9A-V]+$/i,
    36: /^[0-9A-Z]+$/i,
  }

  return regex[selectedBase.value as keyof typeof regex].test(inputValue.value)
})
</script>

<template>
  <div class="mx-auto p-6">
    <div class="flex flex-col space-y-6">
      <!-- 输入区域 -->
      <div>
        <div class="mb-2 flex items-center">
          <span class="text-gray-700 font-medium">输入数值</span>
        </div>
        <div class="flex flex-col gap-4 md:flex-row">
          <div class="flex-grow">
            <input
              v-model="inputValue"
              type="text"
              class="w-full border rounded p-2 font-mono"
              :class="{ 'border-red-500': !isValidInput }"
              placeholder="输入要转换的数值"
            >
            <p v-if="!isValidInput" class="mt-1 text-sm text-red-500">
              输入包含无效字符，不符合所选进制格式
            </p>
          </div>
          <div class="md:w-64">
            <select
              v-model="selectedBase"
              class="w-full border rounded p-2"
            >
              <option v-for="baseType in baseTypes" :key="baseType.value" :value="baseType.value">
                {{ baseType.label }}
              </option>
            </select>
          </div>
        </div>
      </div>

      <!-- 操作按钮 -->
      <div class="flex flex-wrap justify-center gap-4">
        <button
          class="flex items-center gap-2 rounded-lg bg-blue-600 px-6 py-2.5 text-white shadow-sm transition-colors hover:bg-blue-700"
          @click="convertBase"
        >
          <i class="el-icon-refresh" />转换
        </button>
        <button
          class="flex items-center gap-2 rounded-lg bg-red-600 px-6 py-2.5 text-white shadow-sm transition-colors hover:bg-red-700"
          @click="clearInput"
        >
          <i class="el-icon-delete" />清空
        </button>
      </div>

      <!-- 错误信息 -->
      <div v-if="errorMessage" class="rounded bg-red-100 p-3 text-red-700">
        {{ errorMessage }}
      </div>

      <!-- 转换结果 -->
      <div v-if="conversionResults.length > 0" class="space-y-4">
        <h3 class="text-lg font-medium">
          转换结果
        </h3>
        <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div
            v-for="result in conversionResults"
            :key="result.base"
            class="border rounded bg-gray-50 p-4"
          >
            <div class="mb-2 flex items-center justify-between">
              <span class="font-medium">{{ getBaseName(result.base) }}</span>
              <div class="flex space-x-2">
                <button
                  class="text-blue-600 hover:text-blue-800"
                  title="复制结果"
                  @click="copyResult(result.value)"
                >
                  <i class="el-icon-document-copy" />
                </button>
                <button
                  v-if="result.base !== selectedBase"
                  class="text-green-600 hover:text-green-800"
                  title="设为输入"
                  @click="setAsInput(result.base, result.value)"
                >
                  <i class="el-icon-top" />
                </button>
              </div>
            </div>
            <div class="overflow-x-auto border rounded bg-white p-2 font-mono">
              {{ formatBaseValue(result.base, result.value) }}
            </div>
          </div>
        </div>
      </div>

      <!-- 进制说明 -->
      <div class="mt-6 rounded bg-blue-50 p-4">
        <h3 class="mb-2 text-lg font-medium">
          进制说明
        </h3>
        <ul class="list-disc pl-5 space-y-1">
          <li><strong>二进制 (Base 2):</strong> 使用 0 和 1 表示数字</li>
          <li><strong>八进制 (Base 8):</strong> 使用 0-7 表示数字</li>
          <li><strong>十进制 (Base 10):</strong> 使用 0-9 表示数字</li>
          <li><strong>十六进制 (Base 16):</strong> 使用 0-9 和 A-F 表示数字</li>
          <li><strong>三十二进制 (Base 32):</strong> 使用 0-9 和 A-V 表示数字</li>
          <li><strong>三十六进制 (Base 36):</strong> 使用 0-9 和 A-Z 表示数字</li>
        </ul>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 自定义样式 */
</style>
